import sys
import subprocess
from pathlib import Path
import ast
import importlib.util

PACKAGE_NAME = "tcp_nio_module"
PACKAGE_DIR = Path(__file__).parent / PACKAGE_NAME

VERSION_FILE = Path(__file__).parent / PACKAGE_NAME / "__version__.py"

def read_version():
    """读取当前版本"""
    if VERSION_FILE.exists():
        content = VERSION_FILE.read_text().strip()
        if content.startswith("__version__"):
            return content.split("=")[1].strip().strip('"\'')
    return "0.0.0"

def bump_version():
    """自动递增 patch 版本"""
    old_version = read_version()
    major, minor, patch = map(int, old_version.split("."))
    patch += 1
    new_version = f"{major}.{minor}.{patch}"
    VERSION_FILE.write_text(f'__version__ = "{new_version}"\n', encoding="utf-8")
    print(f"[INFO] 版本更新: {old_version} -> {new_version}")
    return new_version

def is_std_lib(module_name: str) -> bool:
    """判断模块是否为 Python 内置标准库"""
    if module_name in sys.builtin_module_names:
        return True
    spec = importlib.util.find_spec(module_name)
    if spec is None or spec.origin is None:
        return False
    return "site-packages" not in spec.origin

def scan_dependencies(package_dir: Path):
    deps = set()
    # 包内部所有模块和子包
    internal_modules = set()
    for py_file in package_dir.rglob("*.py"):
        internal_modules.add(py_file.stem)
        for parent in py_file.parents:
            if parent == package_dir.parent:
                break
            internal_modules.add(parent.name)
    internal_modules.add(PACKAGE_NAME)

    for py_file in package_dir.rglob("*.py"):
        with open(py_file, "r", encoding="utf-8") as f:
            tree = ast.parse(f.read(), filename=str(py_file))
            for node in ast.walk(tree):
                if isinstance(node, ast.Import):
                    for n in node.names:
                        name = n.name.split(".")[0]
                        if name not in internal_modules and not is_std_lib(name):
                            deps.add(name)
                elif isinstance(node, ast.ImportFrom):
                    if node.module:
                        name = node.module.split(".")[0]
                        if name not in internal_modules and not is_std_lib(name):
                            deps.add(name)
    return sorted(deps)

def generate_setup_py(deps, version):
    deps_list = ",\n        ".join(f'"{d}"' for d in deps)
    setup_py_content = f"""from setuptools import setup, find_packages

setup(
    name="{PACKAGE_NAME}",
    version="{version}",
    description="TCP NIO module for ESP32 and Python async",
    author="TreeRoot",
    author_email="xu_genyin@163.com",
    packages=find_packages(),
    include_package_data=True,
    install_requires=[
        {deps_list}
    ],
    python_requires=">=3.10",
)
"""
    (Path(__file__).parent / "setup.py").write_text(setup_py_content, encoding="utf-8")
    print("[INFO] setup.py 已生成")

def generate_manifest():
    manifest_content = "include logs/*\n"
    (Path(__file__).parent / "MANIFEST.in").write_text(manifest_content, encoding="utf-8")
    print("[INFO] MANIFEST.in 已生成")

def install_build_tools():
    print("[INFO] 安装打包工具 setuptools 和 wheel...")
    subprocess.run([sys.executable, "-m", "pip", "install", "--upgrade", "setuptools", "wheel"], check=True)

def build_package():
    print("[INFO] 打包成 Python 安装包...")
    subprocess.run([sys.executable, "setup.py", "sdist", "bdist_wheel"], check=True)
    print("[INFO] 打包完成，生成文件在 dist/ 目录下")

def install_package():
    dist_dir = Path("dist")
    whls = list(dist_dir.glob(f"{PACKAGE_NAME}-*.whl"))
    if whls:
        whl_file = whls[-1]
        print(f"[INFO] 安装 {whl_file} ...")
        subprocess.run([sys.executable, "-m", "pip", "install", "--upgrade", str(whl_file)], check=True)
        print("[INFO] 安装完成")
    else:
        print("[ERROR] dist 目录中未找到 wheel 文件")

def main():
    # 1. 扫描依赖
    deps = scan_dependencies(PACKAGE_DIR)
    print(f"[INFO] 自动扫描依赖: {deps}")

    # 2. 版本管理
    version = bump_version()

    # 3. 生成 setup.py 和 MANIFEST.in
    generate_setup_py(deps, version)
    generate_manifest()

    # 4. 安装打包工具
    install_build_tools()

    # 5. 打包
    build_package()

    # 6. 自动安装
    install_package()

    print("[SUCCESS] 包已打包并安装，可在其他项目直接 import tcp_nio_module")

if __name__ == "__main__":
    main()